#pragma once
#include<iostream>
#include<vector>
#include<pthread.h>
#include<semaphore.h>
template <class T>
class ringqueue
{
public:
	ringqueue(int cap=5)
		:_cap(cap),step_c(0),step_p(0)
	{
		_q.resize(cap);
		sem_init(&space,0,_cap);
		sem_init(&data,0,0);
		pthread_mutex_init(&mtx_c,nullptr);
		pthread_mutex_init(&mtx_p,nullptr);

	};
	~ringqueue()
	{
		sem_destroy(&space);
		sem_destroy(&data);
		pthread_mutex_destroy(&mtx_c);
		pthread_mutex_destroy(&mtx_p);
	}
	void push(const T& val)
	{
	sem_wait(&space);
	pthread_mutex_lock(&mtx_p);
	_q[step_p] =val;
	step_p++;
	step_p%=_cap;
	pthread_mutex_unlock(&mtx_p);
	sem_post(&data);
	}
	void pop(T& out)
	{
	sem_wait(&data);
	pthread_mutex_lock(&mtx_c);
	out = _q[step_c];
	step_c++;
	step_c%=_cap;
	pthread_mutex_unlock(&mtx_c);
	sem_post(&space);
	}
	bool empty()
	{
		int num;
		sem_getvalue(&data,&num);
		return num==0;
	}
	bool full()
	{
		int num;
		sem_getvalue(&space,&num);
		return num==0;
	}


private:
	int _cap;
	vector<T> _q;
	int step_c;
	int step_p;
	sem_t space;
	sem_t data;
	pthread_mutex_t mtx_c;
	pthread_mutex_t mtx_p;

};
